// Fill out your copyright notice in the Description page of Project Settings.


#include "SoulGameplay/SoulKnightPaperCharacter.h"
#include "EnhancedInputSubsystems.h"
#include "InputMappingContext.h"
#include "InputAction.h"
#include "EnhancedInputComponent.h"
#include "Enums/Enums.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Net/UnrealNetwork.h"
#include "PaperFlipbookComponent.h"

ASoulKnightPaperCharacter::ASoulKnightPaperCharacter()
{
	GetCharacterMovement()->MaxWalkSpeed = 200.f;
	MovementState = E_MovementState::Idle;
	FaceToDirection = E_FaceToDirection::Right;
	bReplicates = true;
}

void ASoulKnightPaperCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(ASoulKnightPaperCharacter, MovementState);
}

void ASoulKnightPaperCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	//添加IMC
	if (APlayerController* PlayerController = CastChecked<APlayerController>(GetController()))
	{
		if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
		{
			Subsystem->AddMappingContext(IMC_Move, 100);
		}
	}
	//绑定Action
	if (UEnhancedInputComponent* EnhancedInputComponent = CastChecked<UEnhancedInputComponent>(PlayerInputComponent))
	{
		if (IA_Move)
		{
			EnhancedInputComponent->BindAction(IA_Move, ETriggerEvent::Triggered, this, &ASoulKnightPaperCharacter::Move);
			EnhancedInputComponent->BindAction(IA_Move, ETriggerEvent::Completed, this, &ASoulKnightPaperCharacter::MoveCompleted);
		}
	}
}

void ASoulKnightPaperCharacter::Move(const FInputActionValue& InputValue)
{
	const FVector2D InputDirection = InputValue.Get<FVector2D>();
	if (InputDirection.X == 0.f)
	{
		if (InputDirection.Y == 0.f)
		{
			//切换到待机状态
			ServerSetMovementState(E_MovementState::Idle);	
		}
		else
		{
			ServerSetMovementState(FaceToDirection == E_FaceToDirection::Right ? E_MovementState::MoveRight : E_MovementState::MoveLeft);
		}
	}
	else if (InputDirection.X > 0.f)
	{
		//向右移动
		FaceToDirection = E_FaceToDirection::Right;
		ServerSetMovementState(E_MovementState::MoveRight);
	}
	else if (InputDirection.X < 0.f)
	{
		//向左移动
		FaceToDirection = E_FaceToDirection::Left;
		ServerSetMovementState(E_MovementState::MoveLeft);
	}

	
	if (GetController() && InputValue.GetMagnitude() != 0.f)
	{
		const FRotator Rotation = GetController()->GetControlRotation();
		const FRotator YawRotation(0.f, Rotation.Yaw, 0.f);

		const FVector MovementDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X) * InputDirection.X + FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y) * InputDirection.Y * -1.f;
		AddMovementInput(MovementDirection);
	}
}

void ASoulKnightPaperCharacter::MoveCompleted(const FInputActionValue& InputValue)
{
	ServerSetMovementState(E_MovementState::Idle);
}

void ASoulKnightPaperCharacter::OnRep_MovementState()
{
	MovementStateChanged();
}

void ASoulKnightPaperCharacter::MovementStateChanged()
{
	UPaperFlipbookComponent* PaperFlipbookComp = GetSprite();
	if (!PaperFlipbookComp) return;
	switch (MovementState)
	{
		case E_MovementState::Idle:
			PaperFlipbookComp->SetFlipbook(PlayerAnimFlipbook.IdleFlipbook);
			break;
		case E_MovementState::MoveLeft:
			PaperFlipbookComp->SetRelativeRotation(FRotator(180.f, 0.f, -90.f));
			PaperFlipbookComp->SetFlipbook(PlayerAnimFlipbook.MoveLeftFlipbook);
			break;
		case E_MovementState::MoveRight:
			PaperFlipbookComp->SetRelativeRotation(FRotator(0.f, 0.f, -90.f));
			PaperFlipbookComp->SetFlipbook(PlayerAnimFlipbook.MoveRightFlipbook);
			break;
		default: break;
	}
}

void ASoulKnightPaperCharacter::ServerSetMovementState_Implementation(E_MovementState State)
{
	MovementState = State;
	if (MovementState == E_MovementState::MoveLeft)
	{
		FaceToDirection = E_FaceToDirection::Left;
	}
	else if (MovementState == E_MovementState::MoveRight)
	{
		FaceToDirection = E_FaceToDirection::Right;
	}
	MovementStateChanged();
}
